#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <unistd.h>
#include <time.h>
#define FB_DEV "/dev/fb0"
     
static int fb_dev;
static struct fb_var_screeninfo fb_var;
static int screen_w, screen_h, screen_bits;
static void *fbmem, *data;
static FILE *infile;

typedef struct
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
}COLOR;;
    
typedef struct
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char a;
}PIXEL_T;
    //BMP的内容
typedef struct bmp_file_header
{
  char cfType[2]; //文件类型，必须为“BM”（0x4D42）
  char cfSize[4]; //文件的大小（字节）
  char cfReserved[4]; //保留，必须为0
  char cfoffBits[4]; //位图阵列相对与文件头的偏移量（字节）
}__attribute__((packed)) BITMAPFILEHEADER; //文件头结构
    
typedef struct bmp_info_header
{
  char ciSize[4]; //sizeof of BITMAPINFOHEADER
  char ciWidth[4]; //位图宽度（像素）
  char ciHeight[4]; //位图高度（像素）
  char ciPlanes[2]; //目标设备的位平面数，必须置为1
  char ciBitCount[2]; //每个像素的位数，1，4，8或24
  char ciCompress[4]; //位图阵列的压缩方法，0=不压缩
  char ciSizeImage[4]; //图像大小（字节）
  char ciXPelsPerMeter[4]; //目标设备水平每米像素个数
  char ciYPelsPerMeter[4]; //目标设备垂直每米像素个数
  char ciClrUsed[4]; //位图实际使用的颜色表的颜色数
  char ciClrImportant[4]; //重要颜色索引的个数
}__attribute__((packed)) BITMAPINFOHEADER; //位图信息头结构

unsigned char *fbp;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;

long int screensize;
int xres = 0;
int yres = 0;
int bits_per_pixel = 0;

//初始化fb0
void fb_init()
{
  //打开fb0设备文件
  fb_dev = open(FB_DEV, O_RDWR);
  if(fb_dev < 0)
  {
    printf("Error:open %s error/n", FB_DEV);
    printf("Usage:[sudo ./digital_frame xxx.jpg]/n");
    exit(1);
  }
  //获取fb0参数
  ioctl(fb_dev, FBIOGET_VSCREENINFO, &fb_var);
  screen_w = fb_var.xres;
  screen_h = fb_var.yres;
  screen_bits = fb_var.bits_per_pixel;
  printf("Framebuffer:%d * %d/n", screen_w, screen_h);
  printf("screen_bits:%d/n", screen_bits);
  int screensize=screen_w * screen_h * screen_bits / 8;
  fbmem = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_dev, 0);
  int i=0,bgcolor=0;
  for(i=0;i<screensize;i+=fb_var.bits_per_pixel/8)
  {
    memcpy(fbmem+i,&bgcolor,fb_var.bits_per_pixel/8);
  }
  return;
}
     
//chartolong
long chartolong(char *string, int length)
{
  long number;
  if(length <= 4)
  {
    memset(&number, 0, sizeof(long));
    memcpy(&number, string, length);
  }
  return number;
}
    //显示bmp格式图片
void display_bmp_way1(char *bmpfile)
{
  BITMAPFILEHEADER FileHead;
  BITMAPINFOHEADER InfoHead;
  int rc ,i ,j, x, y,k,l;
  int ciWidth, ciHeight, ciBitCount;
  long int BytesPerLine = 0;
  COLOR picture_color;
  PIXEL_T **fbp;
  unsigned char *buffer, *tmpbuf;
  infile = fopen( bmpfile, "rb" );
  //读位图文件头
  rc = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp header error!\n");
    fclose(infile);
    exit(1);
  }
  //判断位图的类型
  if(memcmp(FileHead.cfType, "BM", 2) != 0)
  {
    printf("This is not a bmp picture!\n");
    fclose(infile);
    exit(1);
  }
  //读取位图信息头
  rc = fread((char *)&InfoHead, sizeof(BITMAPINFOHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp infoheader error!\n");
    fclose(infile);
    exit(1);
  }
  ciWidth = (int)chartolong(InfoHead.ciWidth, 4);
  ciHeight = (int)chartolong(InfoHead.ciHeight, 4);
  ciBitCount = (int)chartolong(InfoHead.ciBitCount, 4);
  fseek(infile, (int)chartolong(FileHead.cfoffBits, 4), SEEK_SET);
  BytesPerLine = (ciWidth * ciBitCount + 31) / 32 * 4;
  printf("图像宽度：%d\n",ciWidth);
  printf("图像高度：%d\n",ciHeight);
  printf("每个像素位数：%d\n",ciBitCount);
  fbp = (PIXEL_T **)malloc(sizeof(PIXEL_T *) * screen_w);
  for(i = 0, x = 0 * screen_bits / 8, y = 0; i < screen_w; i++)
  {
    fbp[i] = (PIXEL_T *)(fbmem + (y + i) * screen_w * screen_bits / 8 + x);
  }
  buffer = (unsigned char *)malloc(BytesPerLine);
  memset(buffer, 0, BytesPerLine);
 
  srand((unsigned)time(NULL));
  int m,n;
  for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = picture_color.r;
       fbp[i][j].g = picture_color.g;
       fbp[i][j].b = picture_color.b;
       tmpbuf += ciBitCount / 8;
     }
  }
  sleep(5);


  for(k=0;k<100000;k++)
  {
    m=rand()%(ciWidth-10);
    n=rand()%(ciHeight-10);
    for(i =n; i <= n+5; i++)
    {
      tmpbuf = buffer;
      rc = fread(tmpbuf, BytesPerLine, 1, infile);
      for(j =m ; j <= m+5; j++)
      {
        memcpy(&picture_color, tmpbuf, ciBitCount / 8);
        fbp[i][j].r = 0;
        fbp[i][j].g = 0;
        fbp[i][j].b = 0;
        tmpbuf += ciBitCount / 8;
       }
     }

    for(l=0;l<10000;l++)
    {}
  }

 for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
       tmpbuf += ciBitCount / 8;
     }
  }
  fclose(infile);
  return ;
}

    //显示bmp格式图片
void display_bmp_way2(char *bmpfile)
{
  BITMAPFILEHEADER FileHead;
  BITMAPINFOHEADER InfoHead;
  int rc ,i ,j, x, y,k,l;
  int ciWidth, ciHeight, ciBitCount;
  long int BytesPerLine = 0;
  COLOR picture_color;
  PIXEL_T **fbp;
  unsigned char *buffer, *tmpbuf;
  infile = fopen( bmpfile, "rb" );
  //读位图文件头
  rc = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp header error!\n");
    fclose(infile);
    exit(1);
  }
  //判断位图的类型
  if(memcmp(FileHead.cfType, "BM", 2) != 0)
  {
    printf("This is not a bmp picture!\n");
    fclose(infile);
    exit(1);
  }
  //读取位图信息头
  rc = fread((char *)&InfoHead, sizeof(BITMAPINFOHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp infoheader error!\n");
    fclose(infile);
    exit(1);
  }
  ciWidth = (int)chartolong(InfoHead.ciWidth, 4);
  ciHeight = (int)chartolong(InfoHead.ciHeight, 4);
  ciBitCount = (int)chartolong(InfoHead.ciBitCount, 4);
  fseek(infile, (int)chartolong(FileHead.cfoffBits, 4), SEEK_SET);
  BytesPerLine = (ciWidth * ciBitCount + 31) / 32 * 4;
  printf("图像宽度：%d\n",ciWidth);
  printf("图像高度：%d\n",ciHeight);
  printf("每个像素位数：%d\n",ciBitCount);
  fbp = (PIXEL_T **)malloc(sizeof(PIXEL_T *) * screen_w);
  for(i = 0, x = 0 * screen_bits / 8, y = 0; i < screen_w; i++)
  {
    fbp[i] = (PIXEL_T *)(fbmem + (y + i) * screen_w * screen_bits / 8 + x);
  }
  buffer = (unsigned char *)malloc(BytesPerLine);
  memset(buffer, 0, BytesPerLine);
 
  srand((unsigned)time(NULL));
  int m,n;
  for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = picture_color.r;
       fbp[i][j].g = picture_color.g;
       fbp[i][j].b = picture_color.b;
       tmpbuf += ciBitCount / 8;
     }
    for(k=0;k<100000;k++)
    {}
  }
  sleep(5);
  for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
       tmpbuf += ciBitCount / 8;
     }
  }
  fclose(infile);
  return ;
}


    //显示bmp格式图片
void display_bmp_way3(char *bmpfile)
{
  BITMAPFILEHEADER FileHead;
  BITMAPINFOHEADER InfoHead;
  int rc ,i ,j, x, y,k,l;
  int ciWidth, ciHeight, ciBitCount;
  long int BytesPerLine = 0;
  COLOR picture_color;
  PIXEL_T **fbp;
  unsigned char *buffer, *tmpbuf;
  infile = fopen( bmpfile, "rb" );
  //读位图文件头
  rc = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp header error!\n");
    fclose(infile);
    exit(1);
  }
  //判断位图的类型
  if(memcmp(FileHead.cfType, "BM", 2) != 0)
  {
    printf("This is not a bmp picture!\n");
    fclose(infile);
    exit(1);
  }
  //读取位图信息头
  rc = fread((char *)&InfoHead, sizeof(BITMAPINFOHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp infoheader error!\n");
    fclose(infile);
    exit(1);
  }
  ciWidth = (int)chartolong(InfoHead.ciWidth, 4);
  ciHeight = (int)chartolong(InfoHead.ciHeight, 4);
  ciBitCount = (int)chartolong(InfoHead.ciBitCount, 4);
  fseek(infile, (int)chartolong(FileHead.cfoffBits, 4), SEEK_SET);
  BytesPerLine = (ciWidth * ciBitCount + 31) / 32 * 4;
  printf("图像宽度：%d\n",ciWidth);
  printf("图像高度：%d\n",ciHeight);
  printf("每个像素位数：%d\n",ciBitCount);
  fbp = (PIXEL_T **)malloc(sizeof(PIXEL_T *) * screen_w);
  for(i = 0, x = 0 * screen_bits / 8, y = 0; i < screen_w; i++)
  {
    fbp[i] = (PIXEL_T *)(fbmem + (y + i) * screen_w * screen_bits / 8 + x);
  }
  buffer = (unsigned char *)malloc(BytesPerLine);
  memset(buffer, 0, BytesPerLine);
 
  srand((unsigned)time(NULL));
  int m,n;
  for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = picture_color.r;
       fbp[i][j].g = picture_color.g;
       fbp[i][j].b = picture_color.b;
       tmpbuf += ciBitCount / 8;
     }
  }
  sleep(5);


for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
       tmpbuf += ciBitCount / 8;
     }
    for(l=0;l<400000;l++)
    {}
  }

 for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
       tmpbuf += ciBitCount / 8;
     }
  }
  fclose(infile);
  return ;
}


    //显示bmp格式图片
void display_bmp_way4(char *bmpfile)
{
  BITMAPFILEHEADER FileHead;
  BITMAPINFOHEADER InfoHead;
  int rc ,i ,j, x, y,k,l;
  int ciWidth, ciHeight, ciBitCount;
  long int BytesPerLine = 0;
  COLOR picture_color;
  PIXEL_T **fbp;
  unsigned char *buffer, *tmpbuf;
  infile = fopen( bmpfile, "rb" );
  //读位图文件头
  rc = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp header error!\n");
    fclose(infile);
    exit(1);
  }
  //判断位图的类型
  if(memcmp(FileHead.cfType, "BM", 2) != 0)
  {
    printf("This is not a bmp picture!\n");
    fclose(infile);
    exit(1);
  }
  //读取位图信息头
  rc = fread((char *)&InfoHead, sizeof(BITMAPINFOHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp infoheader error!\n");
    fclose(infile);
    exit(1);
  }
  ciWidth = (int)chartolong(InfoHead.ciWidth, 4);
  ciHeight = (int)chartolong(InfoHead.ciHeight, 4);
  ciBitCount = (int)chartolong(InfoHead.ciBitCount, 4);
  fseek(infile, (int)chartolong(FileHead.cfoffBits, 4), SEEK_SET);
  BytesPerLine = (ciWidth * ciBitCount + 31) / 32 * 4;
  printf("图像宽度：%d\n",ciWidth);
  printf("图像高度：%d\n",ciHeight);
  printf("每个像素位数：%d\n",ciBitCount);
  fbp = (PIXEL_T **)malloc(sizeof(PIXEL_T *) * screen_w);
  for(i = 0, x = 0 * screen_bits / 8, y = 0; i < screen_w; i++)
  {
    fbp[i] = (PIXEL_T *)(fbmem + (y + i) * screen_w * screen_bits / 8 + x);
  }
  buffer = (unsigned char *)malloc(BytesPerLine);
  memset(buffer, 0, BytesPerLine);
 
  srand((unsigned)time(NULL));
  int m,n;
  for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = picture_color.r;
       fbp[i][j].g = picture_color.g;
       fbp[i][j].b = picture_color.b;
       tmpbuf += ciBitCount / 8;
     }
  }
  sleep(5);

  for(j = 0; j < ciWidth; j++)
  {

    for(i = 0; i <ciHeight; i++)
    {
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
     }
    for(l=0;l<400000;l++)
    {}
  }

 for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
       tmpbuf += ciBitCount / 8;
     }
  }
  fclose(infile);
  return ;
}

    //显示bmp格式图片
void display_bmp_way5(char *bmpfile)
{
  BITMAPFILEHEADER FileHead;
  BITMAPINFOHEADER InfoHead;
  int rc ,i ,j, x, y,k,l;
  int ciWidth, ciHeight, ciBitCount;
  long int BytesPerLine = 0;
  COLOR picture_color;
  PIXEL_T **fbp;
  unsigned char *buffer, *tmpbuf;
  infile = fopen( bmpfile, "rb" );
  //读位图文件头
  rc = fread(&FileHead, sizeof(BITMAPFILEHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp header error!\n");
    fclose(infile);
    exit(1);
  }
  //判断位图的类型
  if(memcmp(FileHead.cfType, "BM", 2) != 0)
  {
    printf("This is not a bmp picture!\n");
    fclose(infile);
    exit(1);
  }
  //读取位图信息头
  rc = fread((char *)&InfoHead, sizeof(BITMAPINFOHEADER), 1, infile);
  if(rc != 1)
  {
    printf("Error:read bmp infoheader error!\n");
    fclose(infile);
    exit(1);
  }
  ciWidth = (int)chartolong(InfoHead.ciWidth, 4);
  ciHeight = (int)chartolong(InfoHead.ciHeight, 4);
  ciBitCount = (int)chartolong(InfoHead.ciBitCount, 4);
  fseek(infile, (int)chartolong(FileHead.cfoffBits, 4), SEEK_SET);
  BytesPerLine = (ciWidth * ciBitCount + 31) / 32 * 4;
  printf("图像宽度：%d\n",ciWidth);
  printf("图像高度：%d\n",ciHeight);
  printf("每个像素位数：%d\n",ciBitCount);
  fbp = (PIXEL_T **)malloc(sizeof(PIXEL_T *) * screen_w);
  for(i = 0, x = 0 * screen_bits / 8, y = 0; i < screen_w; i++)
  {
    fbp[i] = (PIXEL_T *)(fbmem + (y + i) * screen_w * screen_bits / 8 + x);
  }
  buffer = (unsigned char *)malloc(BytesPerLine);
  memset(buffer, 0, BytesPerLine);
 
  srand((unsigned)time(NULL));
  int m,n;
  for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = picture_color.r;
       fbp[i][j].g = picture_color.g;
       fbp[i][j].b = picture_color.b;
       tmpbuf += ciBitCount / 8;
     }
  }
  sleep(5);
 int r=10;
for(r=10;r<1000;r=r+50)
{
  for(j= 0; j < ciWidth;j++ )
  {
    for(i = 0; i <ciHeight;i++)
    {
      if(((j-ciWidth/2)*(j-ciWidth/2)+(i-ciHeight/2)*(i-ciHeight/2))<(r*r)) 
      {
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
       }
     }

  }
}
 for(i = ciHeight - 1; i >= 0; i--)
  {
    tmpbuf = buffer;
    rc = fread(tmpbuf, BytesPerLine, 1, infile);
    for(j = 0; j < ciWidth; j++)
    {
       memcpy(&picture_color, tmpbuf, ciBitCount / 8);
       fbp[i][j].r = 0;
       fbp[i][j].g = 0;
       fbp[i][j].b = 0;
       tmpbuf += ciBitCount / 8;
     }
  }
  fclose(infile);
  return ;
}

int main(int argc, char* argv[])
{
  if(argc != 2)
  {
    printf("Usage:[ + xxx.bmp]\n");
    exit(1);
  }
//fb0初始化
  fb_init();
  display_bmp_way1(argv[1]);
  display_bmp_way2(argv[1]);
  display_bmp_way3(argv[1]);
  display_bmp_way4(argv[1]);
  display_bmp_way5(argv[1]);
  return 0;
}



    
